home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / GUSI 1.4.1 / GUSI / GUSINetDB.cp < prev    next >
Encoding:
Text File  |  1994-05-01  |  10.9 KB  |  490 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    GUSI                -    Grand Unified Socket Interface
  3. File        :    GUSINetDB.cp    -    Convert internet names to adresses
  4. Author    :    Matthias Neeracher
  5.  
  6.     This file was derived from the socket library by
  7.  
  8.         Charlie Reiman    <creiman@ncsa.uiuc.edu> and
  9.         Tom Milligan    <milligan@madhaus.utcs.utoronto.ca>
  10.  
  11. Language    :    MPW C++
  12.  
  13. $Log: GUSINetDB.cp,v $
  14. Revision 1.2  1994/05/01  23:43:31  neeri
  15. getservbyname() without /etc/services would fail.
  16.  
  17. Revision 1.1  1994/02/25  02:29:36  neeri
  18. Initial revision
  19.  
  20. Revision 0.5  1993/10/31  00:00:00  neeri
  21. Deferred opening of resolver
  22.  
  23. Revision 0.4  1993/07/29  00:00:00  neeri
  24. Real getservent code (adapted from Sak Wathanasin)
  25.  
  26. Revision 0.3  1993/01/19  00:00:00  neeri
  27. Can't set aliases to NULL.
  28.  
  29. Revision 0.2  1992/11/21  00:00:00  neeri
  30. Remove force_active
  31.  
  32. Revision 0.1  1992/09/14  00:00:00  neeri
  33. Maybe it works, maybe it doesn't
  34.  
  35. *********************************************************************/
  36.  
  37. #include "GUSIINET_P.h"
  38.  
  39. #include "TFileSpec.h"
  40. #include "Folders.h"
  41. #include "PLStringFuncs.h"
  42.  
  43. #pragma segment GUSIResident
  44. pascal void DNRDone(struct hostInfo *, Boolean * done)
  45. {
  46.     *done = true;
  47. }
  48.  
  49. #pragma segment GUSIINET
  50.  
  51. int h_errno;
  52.  
  53. /*
  54.  *   Gethostbyname and gethostbyaddr each return a pointer to an
  55.  *   object with the following structure describing an Internet
  56.  *   host referenced by name or by address, respectively. This
  57.  *   structure contains the information obtained from the MacTCP
  58.  *   name server.
  59.  *
  60.  *   struct    hostent
  61.  *   {
  62.  *        char *h_name;
  63.  *        char **h_aliases;
  64.  *        int  h_addrtype;
  65.  *        int  h_length;
  66.  *        char **h_addr_list;
  67.  *   };
  68.  *   #define   h_addr  h_addr_list[0]
  69.  *
  70.  *   The members of this structure are:
  71.  *
  72.  *   h_name       Official name of the host.
  73.  *
  74.  *   h_aliases    A zero terminated array of alternate names for the host.
  75.  *
  76.  *   h_addrtype   The type of address being  returned; always AF_INET.
  77.  *
  78.  *   h_length     The length, in bytes, of the address.
  79.  *
  80.  *   h_addr_list  A zero terminated array of network addresses for the host.
  81.  *
  82.  *   Error return status from gethostbyname and gethostbyaddr  is
  83.  *   indicated by return of a null pointer.  The external integer
  84.  *   h_errno may then  be checked  to  see  whether  this  is  a
  85.  *   temporary  failure  or  an  invalid  or  unknown  host.  The
  86.  *   routine herror  can  be  used  to  print  an error  message
  87.  *   describing the failure.  If its argument string is non-NULL,
  88.  *   it is printed, followed by a colon and a space.   The  error
  89.  *   message is printed with a trailing newline.
  90.  *
  91.  *   h_errno can have the following values:
  92.  *
  93.  *     HOST_NOT_FOUND  No such host is known.
  94.  *
  95.  *     TRY_AGAIN    This is usually a temporary error and
  96.  *                    means   that  the  local  server  did  not
  97.  *                    receive a response from  an  authoritative
  98.  *                    server.   A  retry at some later time may
  99.  *                    succeed.
  100.  *
  101.  *     NO_RECOVERY    Some unexpected server failure was encountered.
  102.  *                     This is a non-recoverable error.
  103.  *
  104.  *     NO_DATA        The requested name is valid but  does  not
  105.  *                    have   an IP  address;  this  is not  a
  106.  *                    temporary error. This means that the  name
  107.  *                    is known  to the name server but there is
  108.  *                    no address  associated  with  this  name.
  109.  *                    Another type of request to the name server
  110.  *                    using this domain name will result in  an
  111.  *                    answer;  for example, a mail-forwarder may
  112.  *                    be registered for this domain.
  113.  *                    (NOT GENERATED BY THIS IMPLEMENTATION)
  114.  */
  115.  
  116. static struct hostInfo macHost;
  117.  
  118. #define MAXALIASES 0
  119. static char *aliasPtrs[MAXALIASES+1] = {NULL};
  120. static ip_addr *addrPtrs[NUM_ALT_ADDRS+1];
  121.  
  122. static struct hostent  unixHost =
  123. {
  124.     macHost.cname,
  125.     aliasPtrs,
  126.     AF_INET,
  127.     sizeof(ip_addr),
  128.     (char **) addrPtrs
  129. };
  130.  
  131. inline struct in_addr make_in_addr(ip_addr addr)
  132. {
  133.     struct in_addr    res;
  134.  
  135.     res.s_addr    =    addr;
  136.  
  137.     return res;
  138. }
  139.  
  140. struct hostent * gethostbyname(char *name)
  141. {
  142.     Boolean done;
  143.     int i;
  144.  
  145.     if (INETSockets.Resolver()) {
  146.         h_errno = NO_RECOVERY;    
  147.         return NULL;
  148.     }
  149.     
  150.     for (i=0; i<NUM_ALT_ADDRS; i++)
  151.         macHost.addr[i] = 0;
  152.  
  153.     done = false;
  154.  
  155.     if (StrToAddr(name, &macHost, ResultProcPtr(DNRDone), (char *) &done) == cacheFault)
  156.         SPINP(!done,SP_NAME,0L);
  157.  
  158.     switch (macHost.rtnCode) {
  159.     case noErr: break;
  160.  
  161.     case nameSyntaxErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  162.     case cacheFault:        h_errno = NO_RECOVERY;        return(NULL);
  163.     case noResultProc:    h_errno = NO_RECOVERY;        return(NULL);
  164.     case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  165.     case authNameErr:        h_errno = HOST_NOT_FOUND;    return(NULL);
  166.     case noAnsErr:            h_errno = TRY_AGAIN;            return(NULL);
  167.     case dnrErr:            h_errno = NO_RECOVERY;        return(NULL);
  168.     case outOfMemory:        h_errno = TRY_AGAIN;            return(NULL);
  169.     default:                    h_errno = NO_RECOVERY;        return(NULL);
  170.     }
  171.  
  172.     /* was the 'name' an IP address? */
  173.     if (macHost.cname[0] == 0) {
  174.         h_errno = HOST_NOT_FOUND;
  175.         return(NULL);
  176.     }
  177.  
  178.     /* for some reason there is a dot at the end of the name */
  179.     i = strlen(macHost.cname) - 1;
  180.     if (macHost.cname[i] == '.')
  181.         macHost.cname[i] = 0;
  182.  
  183.     for (i=0; i<NUM_ALT_ADDRS && macHost.addr[i]!=0; i++)
  184.         addrPtrs[i] =    (ip_addr *) &macHost.addr[i];
  185.  
  186.     addrPtrs[i] = NULL;
  187.  
  188.     return &unixHost;
  189. }
  190.  
  191. struct hostent * gethostbyaddr(const char *addrP, int, int)
  192. {
  193.     Boolean    done;
  194.     int         i;
  195.  
  196.     if (INETSockets.Resolver()) {
  197.         h_errno = NO_RECOVERY;    
  198.         return NULL;
  199.     }
  200.  
  201.     for (i=0; i<NUM_ALT_ADDRS; i++)
  202.         macHost.addr[i] = 0;
  203.  
  204.     done = false;
  205.  
  206.     if (AddrToName(*(ip_addr *)addrP, &macHost, ResultProcPtr(DNRDone), (char *) &done) == cacheFault)
  207.         SPINP(!done,SP_ADDR,0L);
  208.  
  209.     switch (macHost.rtnCode) {
  210.     case noErr:             break;
  211.  
  212.     case cacheFault:        h_errno = NO_RECOVERY;        return(NULL);
  213.     case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  214.     case authNameErr:        h_errno = HOST_NOT_FOUND;    return(NULL);
  215.     case noAnsErr:            h_errno = TRY_AGAIN;            return(NULL);
  216.     case dnrErr:            h_errno = NO_RECOVERY;        return(NULL);
  217.     case outOfMemory:        h_errno = TRY_AGAIN;            return(NULL);
  218.     default:                    h_errno = NO_RECOVERY;        return(NULL);
  219.     }
  220.  
  221.     /* for some reason there is a dot at the end of the name */
  222.     i = strlen(macHost.cname) - 1;
  223.     if (macHost.cname[i] == '.')
  224.         macHost.cname[i] = 0;
  225.  
  226.     for (i=0; i<NUM_ALT_ADDRS; i++)
  227.         addrPtrs[i] = (ip_addr *) &macHost.addr[i];
  228.  
  229.     addrPtrs[NUM_ALT_ADDRS] = NULL;
  230.  
  231.     return &unixHost;
  232. }
  233.  
  234. char * inet_ntoa(struct in_addr inaddr)
  235. {
  236.     if (INETSockets.Resolver()) {
  237.         h_errno = NO_RECOVERY;    
  238.         return NULL;
  239.     }
  240.     
  241.     (void) AddrToStr(inaddr.s_addr, macHost.cname);
  242.  
  243.     return macHost.cname;
  244. }
  245.  
  246. struct in_addr inet_addr(char *address)
  247. {
  248.     if (INETSockets.Resolver()) {
  249.         h_errno = NO_RECOVERY;    
  250.         return make_in_addr(0xFFFFFFFF);
  251.     }
  252.     
  253.     if (StrToAddr(address,&macHost,NULL,NULL) != noErr)
  254.         return make_in_addr(0xFFFFFFFF);
  255.  
  256.     /* was the 'address' really a name? */
  257.     if (macHost.cname[0] != 0)
  258.         return make_in_addr(0xFFFFFFFF);
  259.  
  260.     return make_in_addr(macHost.addr[0]);
  261. }
  262.  
  263. /*
  264.  * gethostname()
  265.  *
  266.  * Try to get my host name from DNR. If it fails, just return my
  267.  * IP address as ASCII. This is non-standard, but it's a mac,
  268.  * what do you want me to do?
  269.  */
  270.  
  271. int gethostname(char *machname, int buflen)
  272. {
  273.     in_addr ipaddr;
  274.     struct    hostent *hp;
  275.     struct GetAddrParamBlock pbr;
  276.  
  277.     pbr.ioCRefNum     = INETSockets.Driver();
  278.     pbr.csCode         = ipctlGetAddr;
  279.  
  280.     if (PBControlSync(ParmBlkPtr(&pbr)))
  281.         goto resign;
  282.  
  283.     ipaddr    =    make_in_addr(pbr.ourAddress);
  284.  
  285.     hp = gethostbyaddr((char *) &ipaddr, sizeof(in_addr), AF_INET);
  286.  
  287.     if (!hp)
  288.         goto resign;
  289.     else
  290.         strncpy(machname, hp->h_name, unsigned(buflen));
  291.  
  292.     machname[buflen-1] = 0;  /* extra safeguard */
  293.  
  294.     return 0;
  295.  
  296. resign:
  297.     sprintf(machname, "%d.%d.%d.%d",
  298.                             ipaddr.s_addr>>24,
  299.                             ipaddr.s_addr>>16 & 0xff,
  300.                             ipaddr.s_addr>>8 & 0xff,
  301.                             ipaddr.s_addr & 0xff);
  302.     return 0;
  303. }
  304.  
  305.  
  306. /*
  307.  *    getservbybname()
  308.  *
  309.  */
  310.  
  311. static char * servlist[] =
  312. {
  313.     "echo             7/udp",
  314.     "discard         9/udp",
  315.     "time            37/udp",
  316.     "domain        53/udp",
  317.     "sunrpc       111/udp",
  318.     "tftp           69/udp",
  319.     "biff           512/udp",
  320.     "who           513/udp",
  321.     "talk           517/udp",
  322.     "ftp-data       20/tcp",
  323.     "ftp           21/tcp",
  324.     "telnet       23/tcp",
  325.     "smtp           25/tcp",
  326.     "time           37/tcp",
  327.     "whois           43/tcp",
  328.     "domain           53/tcp",
  329.     "hostnames  101/tcp",
  330.     "nntp           119/tcp",
  331.     "finger       79/tcp",
  332.     "ntp           123/tcp",
  333.     "uucp           540/tcp",
  334.     NULL
  335. };
  336.  
  337. static char                 servline[128];
  338. static struct servent    serv;
  339. static FILE *                 servfil;
  340. static int                    servptr;
  341. static char *                servalias[8];
  342. static int                    servstay = 0;
  343.  
  344. void setservent(int stayopen)
  345. {
  346.     if (servfil && servfil != (FILE *) -1) {
  347.         rewind(servfil);
  348.     }
  349.     servptr    = 0;
  350.     servstay = servstay || stayopen;
  351. }
  352.  
  353. void endservent()
  354. {
  355.     if (servfil && servfil != (FILE *) -1) {
  356.         fclose(servfil);
  357.         servfil = NULL;
  358.     }
  359.     
  360.     servstay = 0;
  361. }
  362.  
  363. struct servent *  getservent()
  364. {
  365.     char *    p;
  366.     int        aliascount;
  367.     
  368.     if (!servfil) {
  369.         TFileSpec serv;
  370.         
  371.         if (!FindFolder(
  372.                 kOnSystemDisk, 
  373.                 kPreferencesFolderType, 
  374.                 kDontCreateFolder, 
  375.                 &serv.vRefNum,
  376.                 &serv.parID)
  377.         ) {
  378.             PLstrcpy(serv.name, "\p/etc/services");
  379.         
  380.             if (servfil = fopen(serv.FullPath(), "r"))
  381.                 goto retry;
  382.         }    
  383.         servfil     = (FILE *) -1;
  384.         servptr    = 0;
  385.     }
  386.     
  387. retry:
  388.     if (servfil == (FILE *) -1)
  389.         if (!servlist[servptr])
  390.             return (struct servent *) NULL;
  391.         else
  392.             strcpy(servline, servlist[servptr++]);
  393.     else if (!(fgets(servline, 128, servfil)))
  394.         return (struct servent *) NULL;
  395.         
  396.     if (p = strpbrk(servline, "#\n"))
  397.         *p = 0;
  398.     if (!servline[0])
  399.         goto retry;
  400.     
  401.     if (!(serv.s_name = strtok(servline, " \t")))
  402.         goto retry;
  403.         
  404.     if (!(p = strtok(NULL, " \t")))
  405.         goto retry;
  406.     
  407.     if (!(serv.s_proto = strpbrk(p, "/,")))
  408.         goto retry;
  409.         
  410.     *serv.s_proto++     = 0;
  411.     serv.s_port         = htons(atoi(p));
  412.     serv.s_aliases     = servalias;
  413.     
  414.     for (aliascount = 0; aliascount < 7; ) 
  415.         if (!(servalias[aliascount++] = strtok(NULL, " \t")))
  416.             break;
  417.     
  418.     servalias[aliascount] = NULL;
  419.     
  420.     return &serv;
  421. }
  422.  
  423. struct servent * getservbyname(const char * name, const char * proto)
  424. {
  425.     struct servent *     ent;
  426.     char **                 al;
  427.     setservent(0);
  428.     
  429.     while (ent = getservent()) {
  430.         if (!strcmp(name, ent->s_name))
  431.             goto haveName;
  432.         
  433.         for (al = ent->s_aliases; *al; ++al)
  434.             if (!strcmp(name, *al))
  435.                 goto haveName;
  436.         
  437.         continue;
  438. haveName:
  439.         if (!proto || !strcmp(proto, ent->s_proto))
  440.             break;
  441.     }
  442.     
  443.     if (!servstay)
  444.         endservent();
  445.     
  446.     return ent;
  447. }
  448.  
  449. struct servent * getservbyport(int port, const char * proto)
  450. {
  451.     struct servent * ent;
  452.     
  453.     setservent(0);
  454.     
  455.     while (ent = getservent())
  456.         if (port == ent->s_port && (!proto || !strcmp(proto, ent->s_proto)))
  457.             break;
  458.     
  459.     if (!servstay)
  460.         endservent();
  461.     
  462.     return ent;
  463. }
  464.  
  465. static    char    tcp[] = "tcp";
  466. static    char    udp[] = "udp";
  467. #define    MAX_PROTOENT            10
  468. static     struct protoent        protoents[MAX_PROTOENT];
  469. static     int                        protoent_count=0;
  470.  
  471. struct protoent * getprotobyname(const char * name)
  472. {
  473.     struct protoent *pe;
  474.  
  475.     pe = &protoents[protoent_count];
  476.     if (strcmp(name, "udp") == 0) {
  477.         pe->p_name = udp;
  478.         pe->p_proto = IPPROTO_UDP;
  479.     } else if (strcmp (name, "tcp") == 0)  {
  480.         pe->p_name = tcp;
  481.         pe->p_proto = IPPROTO_TCP;
  482.     } else {
  483.         errno = EPROTONOSUPPORT;
  484.         return NULL;
  485.     }
  486.     pe->p_aliases = aliasPtrs;
  487.     protoent_count = (protoent_count +1) % MAX_PROTOENT;
  488.     return pe;
  489. }
  490.